package cn.imnu.legalaid.service.impl;

import cn.imnu.legalaid.dto.Appointment.AppointmentCreateDTO;
import cn.imnu.legalaid.dto.Appointment.AppointmentDTO;
import cn.imnu.legalaid.dto.Appointment.AppointmentQueryDTO;
import cn.imnu.legalaid.dto.Appointment.AppointmentUpdateDTO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.imnu.legalaid.entity.Appointments;
import cn.imnu.legalaid.service.AppointmentsService;
import cn.imnu.legalaid.mapper.AppointmentsMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
* @author 18498
* @description 针对表【appointments(预约表)】的数据库操作Service实现
* @createDate 2025-09-19 17:49:09
*/
@Service
public class AppointmentsServiceImpl extends ServiceImpl<AppointmentsMapper, Appointments>
    implements AppointmentsService{

    @Override
    public Integer createAppointment(AppointmentCreateDTO createDTO) {
        // 检查时间冲突
        if (checkTimeConflict(createDTO.getLawyerId(), createDTO.getScheduledTime(),
                createDTO.getDuration(), null)) {
            throw new RuntimeException("预约时间与律师其他预约冲突");
        }

        Appointments appointment = new Appointments();
        BeanUtils.copyProperties(createDTO, appointment);
        appointment.setClient_id(createDTO.getClientId());
        appointment.setLawyer_id(createDTO.getLawyerId());
        appointment.setScheduled_time(createDTO.getScheduledTime());
        appointment.setAppointment_fee(createDTO.getAppointmentFee());
        appointment.setStatus("pending"); // 默认状态为待确认
        appointment.setCreated_at(LocalDateTime.now());
        appointment.setUpdated_at(LocalDateTime.now());

        this.save(appointment);
        return appointment.getId();
    }

    @Override
    public Page<AppointmentDTO> getAppointments(Page<AppointmentDTO> page, AppointmentQueryDTO queryDTO) {
        QueryWrapper<Appointments> queryWrapper = new QueryWrapper<>();

        // 添加查询条件
        if (queryDTO.getClientId() != null) {
            queryWrapper.eq("client_id", queryDTO.getClientId());
        }
        if (queryDTO.getLawyerId() != null) {
            queryWrapper.eq("lawyer_id", queryDTO.getLawyerId());
        }
        if (queryDTO.getStatus() != null && !queryDTO.getStatus().isEmpty()) {
            queryWrapper.eq("status", queryDTO.getStatus());
        }
        if (queryDTO.getType() != null && !queryDTO.getType().isEmpty()) {
            queryWrapper.eq("type", queryDTO.getType());
        }
        if (queryDTO.getStartTime() != null) {
            queryWrapper.ge("scheduled_time", queryDTO.getStartTime());
        }
        if (queryDTO.getEndTime() != null) {
            queryWrapper.le("scheduled_time", queryDTO.getEndTime());
        }

        queryWrapper.orderByDesc("created_at");

        Page<Appointments> appointmentPage = new Page<>(page.getCurrent(), page.getSize());
        Page<Appointments> result = this.page(appointmentPage, queryWrapper);

        // 转换为DTO
        List<AppointmentDTO> dtoList = result.getRecords().stream()
                .map(this::convertToDTO)
                .collect(Collectors.toList());

        Page<AppointmentDTO> dtoPage = new Page<>();
        BeanUtils.copyProperties(result, dtoPage);
        dtoPage.setRecords(dtoList);

        return dtoPage;
    }

    @Override
    public AppointmentDTO getAppointmentDetail(Integer id) {
        Appointments appointment = this.getById(id);
        if (appointment == null) {
            return null;
        }
        return convertToDTO(appointment);
    }

    @Override
    public AppointmentDTO updateAppointment(Integer id, AppointmentUpdateDTO updateDTO) {
        Appointments appointment = this.getById(id);
        if (appointment == null) {
            throw new RuntimeException("预约不存在");
        }

        // 如果更新时间，需要检查冲突
        if (updateDTO.getScheduledTime() != null &&
                !updateDTO.getScheduledTime().equals(appointment.getScheduled_time())) {
            if (checkTimeConflict(appointment.getLawyer_id(), updateDTO.getScheduledTime(),
                    updateDTO.getDuration() != null ? updateDTO.getDuration() : appointment.getDuration(), id)) {
                throw new RuntimeException("预约时间与律师其他预约冲突");
            }
        }

        // 更新字段
        if (updateDTO.getScheduledTime() != null) {
            appointment.setScheduled_time(updateDTO.getScheduledTime());
        }
        if (updateDTO.getDuration() != null) {
            appointment.setDuration(updateDTO.getDuration());
        }
        if (updateDTO.getPurpose() != null) {
            appointment.setPurpose(updateDTO.getPurpose());
        }
        if (updateDTO.getType() != null) {
            appointment.setType(updateDTO.getType());
        }
        if (updateDTO.getAppointmentFee() != null) {
            appointment.setAppointment_fee(updateDTO.getAppointmentFee());
        }
        if (updateDTO.getStatus() != null) {
            appointment.setStatus(updateDTO.getStatus());
        }
        appointment.setUpdated_at(LocalDateTime.now());

        this.updateById(appointment);
        return convertToDTO(appointment);
    }

    @Override
    public void cancelAppointment(Integer id) {
        updateAppointmentStatus(id, "cancelled");
    }

    @Override
    public void confirmAppointment(Integer id) {
        updateAppointmentStatus(id, "confirmed");
    }

    @Override
    public void completeAppointment(Integer id) {
        updateAppointmentStatus(id, "completed");
    }

    @Override
    public void updateAppointmentStatus(Integer id, String status) {
        Appointments appointment = this.getById(id);
        if (appointment == null) {
            throw new RuntimeException("预约不存在");
        }

        appointment.setStatus(status);
        appointment.setUpdated_at(LocalDateTime.now());
        this.updateById(appointment);
    }

    @Override
    public boolean checkTimeConflict(Integer lawyerId, LocalDateTime scheduledTime, Integer duration, Integer excludeId) {
        if (scheduledTime == null || duration == null) {
            return false;
        }

        LocalDateTime endTime = scheduledTime.plusMinutes(duration);

        QueryWrapper<Appointments> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("lawyer_id", lawyerId);
        queryWrapper.in("status", "pending", "confirmed"); // 只检查待确认和已确认的预约

        if (excludeId != null) {
            queryWrapper.ne("id", excludeId);
        }

        // 检查时间重叠：新预约开始时间在现有预约时间范围内，或新预约结束时间在现有预约时间范围内
        queryWrapper.and(wrapper ->
                wrapper.and(w ->
                        w.le("scheduled_time", scheduledTime)
                                .ge("DATE_ADD(scheduled_time, INTERVAL duration MINUTE)", scheduledTime)
                ).or(w ->
                        w.le("scheduled_time", endTime)
                                .ge("DATE_ADD(scheduled_time, INTERVAL duration MINUTE)", endTime)
                ).or(w ->
                        w.ge("scheduled_time", scheduledTime)
                                .le("scheduled_time", endTime)
                )
        );

        return this.count(queryWrapper) > 0;
    }

    /**
     * 转换实体为DTO
     */
    private AppointmentDTO convertToDTO(Appointments appointment) {
        AppointmentDTO dto = new AppointmentDTO();
        BeanUtils.copyProperties(appointment, dto);
        dto.setClientId(appointment.getClient_id());
        dto.setLawyerId(appointment.getLawyer_id());
        dto.setScheduledTime(appointment.getScheduled_time());
        dto.setAppointmentFee(appointment.getAppointment_fee());
        dto.setCreatedAt(appointment.getCreated_at());
        dto.setUpdatedAt(appointment.getUpdated_at());

        // TODO: 这里可以添加客户和律师姓名的查询
        // 需要注入UserService或相关服务来获取姓名信息

        return dto;
    }

}




